﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDD {

    /// <summary>
    /// バウンディングボリューム
    /// </summary>
    /// <remarks>
    /// バウンディングボリュームは物体を囲う領域を定義するコンポーネントの一種です。
    /// このコンポーネントがアタッチされたノードはカリング、ピッキング、LOD選択などの対象となります。
    /// (アタッチされていない場合は対象となりません)
    /// バウンディングボリュームは箱状の<see cref="BoundingBox"/>または球状の<see cref="BoundingSphere"/>から構成されます。
    /// 両者は両方同時に指定可能です。
    /// 
    /// </remarks>
    public class BoundingVolume : Component {

        #region Field
        BoundingSphere bsph;
        BoundingBox bbox;
        #endregion

        #region Constructor
        /// <summary>
        /// コンストラクター
        /// </summary>
        /// <remarks>
        /// 空のバウンディングボリュームを作成します。
        /// </remarks>
        public void BoudingVolume () {
            this.bsph = new BoundingSphere ();
            this.bbox = new BoundingBox ();
        }
        #endregion

        #region Property
        /// <summary>
        /// バウンディングボックス
        /// </summary>
        public BoundingBox BoundingBox {
            get { return bbox; }
            private set { this.bbox = value; }
        }

        /// <summary>
        /// バウンディングスフィア
        /// </summary>
        public BoundingSphere BoundingSphere {
            get { return bsph; }
            private set { this.bsph = value; }
        }

        /// <summary>
        /// このオブジェクトが参照する全DDDオブジェクトを列挙する列挙子
        /// </summary>
        /// <remarks>
        /// 参照にnullは含まれません。同一のオブジェクトが複数出現する可能性があります。
        /// </remarks>
        public override IEnumerable<Object> References {
            get {
                return base.References;
            }
        }
        #endregion

        #region Method
        /// <summary>
        /// バウンディングスフィアをセットします
        /// </summary>
        /// <remarks>
        /// このバウンディングボリュームに指定のバウンディングスフィアを追加します。
        /// 全ての要素に0を指定するとバウンディングスフィアは無効になります。
        /// </remarks>
        /// <param name="radius">半径</param>
        /// <param name="x">原点のX座標</param>
        /// <param name="y">原点のY座標</param>
        /// <param name="z">原点のZ座標</param>
        public void SetBoundingSphere (float radius, float x, float y, float z) {
            if (radius < 0) {
                throw new ArgumentException ("Radius is invalid");
            }
            this.bsph = new BoundingSphere (radius, x, y, z);
        }

        /// <summary>
        /// バウンディングボックスの追加
        /// </summary>
        /// <remarks>
        /// このバウンディングボリュームに指定のバウンディングボックスを追加します。
        /// 全ての要素に0を指定するとバウンディングボックスは無効になります。
        /// </remarks>
        /// <param name="minX">X軸方向の下限</param>
        /// <param name="maxX">X軸方向の上限</param>
        /// <param name="minY">Y軸方向の下限</param>
        /// <param name="maxY">Y軸方向の上限</param>
        /// <param name="minZ">Z軸方向の下限</param>
        /// <param name="maxZ">Z軸方向の上限</param>
        public void SetBoundingBox (float minX, float maxX, float minY, float maxY, float minZ, float maxZ) {
            this.bbox = new BoundingBox (minX, maxX, minY, maxY, minZ, maxZ);
        }

        /// <summary>
        /// 現在のオブジェクトの状態を表す文字列を返します。
        /// </summary>
        public override string ToString () {
            return string.Format ("BoundingVolume: Box={0}, Sphere={1}", BoundingBox.IsValid, BoundingSphere.IsValid);
        }

        #endregion

    }
}
